#include <stdint.h>
#include <string.h>
#include <stdbool.h>

#include "fx_power.h"
#include "fx_gpio.h"
#include "fx_spi.h"

#include "aoaoutil.h"
#include "rtthread.h"

#include "fx_aperture.h"

#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))

// struct rt_event aperture_event;
struct rt_event APERTURE_EVENT;

uint32_t FX_APERTURE_READ_VALUE = 0;
uint32_t FX_APERTURE_WRITE_VALUE = 0;

static int fx_aperture_init(void)
{
    rt_event_init(&APERTURE_EVENT, "aperture", RT_IPC_FLAG_FIFO);
    return 0;
}
INIT_PREV_EXPORT(fx_aperture_init);

// aperture_value = 0x70401882; // F2.2
// aperture_value = 0x70C01886; // F2.8
// aperture_value = 0x71001888; // F3.2
// aperture_value = 0x72401892; // F5.6
// aperture_value = 0x73001898; // F8.0
void fx_aperture_write(uint32_t aperture_value)
{
    rt_kprintf("fx_aperture_write: 0x%08X\n", aperture_value);

    // static uint32_t write_data[] = {
    //     0x00000FC0, 0x0E108012, 0x00000000, 0x08008FD2, 0x00010842, 0x0F10801A, 0x00000000, 0x08008874, 0x80042808,
    //     0x08108022, 0x00001864, 0x0900A83E, 0x73001898, 0x0A009846, 0x00003FC6, 0x0B00988E, 0x00000000, 0x0800BFD8,
    // };
    static uint32_t write_data[] = {
        0x80042808, 0x08108022, 0x00001864, 0x0900A83E, 0x73001898,
        0x0A009846, 0x00003FC6, 0x0B00988E, 0x00000000, 0x0800BFD8,
    };

    // 0x00001864 之后的第2个数据，高位必须0x7
    // aperture_value = 0x70401882;

    // 最大值无需发指令

    for (size_t i = 0; i < ARRAY_LEN(write_data); i++)
    {
        if (write_data[i] == 0x00001864)
        {
            write_data[i + 2] = aperture_value;
            break;
        }
    }

    static uint32_t read_data[ARRAY_LEN(write_data)] = {0};

    for (uint8_t i = 0; i < ARRAY_LEN(write_data); i++)
    {
        fx_spi_tr(write_data + i, read_data + i);
        if (i != (ARRAY_LEN(write_data) - 1))
        {
            rt_thread_mdelay(1);
        }
    }

    // log_wrdata(write_data, read_data, ARRAY_LEN(write_data));
    // rt_kprintf("\n");
}

void fx_aperture_read(uint32_t *aperture_value)
{
    static uint32_t write_data[] = {0x00000C30, 0x0A108032, 0x00000000, 0x08008C02};
    static uint32_t read_data[ARRAY_LEN(write_data)] = {0};

    for (uint8_t i = 0; i < ARRAY_LEN(write_data); i++)
    {
        fx_spi_tr(write_data + i, read_data + i);
        if (i != (ARRAY_LEN(write_data) - 1))
        {
            rt_thread_mdelay(1);
        }
    }

    if (aperture_value != NULL)
    {
        *aperture_value = read_data[2];
    }
}

static int msh_aperture(int argc, void **argv)
{
    rt_err_t ret;
    // rt_kprintf("argc: %d\n", argc);
    // rt_kprintf("argv[0]: %s\n", argv[0]);
    // rt_kprintf("argv[0]: %s\n", argv[1]);
    // rt_kprintf("argv[0]: %s\n", argv[2]);

    switch (argc)
    {
    case 1:
        rt_kprintf("lens aperture example:\n");
        rt_kprintf("    aperture r\n");
        rt_kprintf("    aperture w 0\n");
        rt_kprintf("    aperture w 2\n");
        break;

    case 2:
        if (rt_strcmp(argv[1], "r") == 0)
        {
            rt_event_send(&APERTURE_EVENT, FX_APERTURE_EVENT_READ_REQUEST);
            ret = rt_event_recv(&APERTURE_EVENT, FX_APERTURE_EVENT_READ_DONE, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                                1000, NULL);
            if (ret != RT_EOK)
            {
                rt_kprintf("aperture read error\n");
            }
            else
            {
                rt_kprintf("aperture value: 0x%08X\n", FX_APERTURE_READ_VALUE);
            }
            break;
        }

        rt_kprintf("parameter error\n");
        break;

    case 3:
        if (rt_strcmp(argv[1], "w") == 0)
        {
            // rt_kprintf("aperture set %s\n", argv[2]);
            char v = (char)(((char *)argv[2])[0]);

            static uint32_t __APERTURE_VALUE_LIST[] = {
                0x100018A8, 0x70001880, 0x70401882, 0x70801884, 0x70C01886, 0x71001888,
                0x7140188A, 0x7180188C, 0x71C0188E, 0x72001890, 0x72401892, 0x72801894,
                0x72C01896, 0x73001898, 0x7340189A, 0x7380189C, 0x73C0189E, 0x740018A0,
            };

            if (v >= '0' && v <= ('0' + ARRAY_LEN(__APERTURE_VALUE_LIST)))
            {

                FX_APERTURE_WRITE_VALUE = __APERTURE_VALUE_LIST[v - '0'];

                rt_event_send(&APERTURE_EVENT, FX_APERTURE_EVENT_WRITE_REQUEST);

                ret = rt_event_recv(&APERTURE_EVENT, FX_APERTURE_EVENT_WRITE_DONE,
                                    RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 1000, NULL);

                if (ret != RT_EOK)
                {
                    rt_kprintf("aperture write error\n");
                }

                break;
            }
        }

        rt_kprintf("parameter error\n");
        break;

    default:
        rt_kprintf("too many\n");
        break;
    }

    return 0;
}
MSH_CMD_EXPORT_ALIAS(msh_aperture, aperture, lens aperture);
